package com.un.ebs.inventory.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.un.ebs.core.enums.IndustryTypeEnum;
import com.un.ebs.core.enums.UserTypeEnum;
import com.un.ebs.core.exception.BusinessException;
import com.un.ebs.core.util.SecurityUtils;
import com.un.ebs.core.util.StringUtils;
import com.un.ebs.inventory.domain.EntRelation;
import com.un.ebs.inventory.domain.EntRelationApiHandler;
import com.un.ebs.inventory.domain.EntRelationExt;
import com.un.ebs.inventory.dto.BusinessSupplyEntDto;
import com.un.ebs.inventory.dto.EntRelationApiHandlerDto;
import com.un.ebs.inventory.dto.EntRelationDto;
import com.un.ebs.inventory.dto.EntRelationUpdateDto;
import com.un.ebs.inventory.enums.BusinessRelationTypeEnum;
import com.un.ebs.inventory.mapper.EntRelationApiHandlerMapper;
import com.un.ebs.inventory.mapper.EntRelationExtMapper;
import com.un.ebs.inventory.mapper.EntRelationMapper;
import com.un.ebs.inventory.service.BusinessRelationService;
import com.un.ebs.sys.domain.UserExt;
import com.un.ebs.sys.dto.EntAddDto;
import com.un.ebs.sys.dto.EntUpdateDto;
import com.un.ebs.sys.service.EntService;
import com.un.ebs.sys.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author liubo
 * @email liubocs@163.com
 * @date 2020/5/28 11:51
 */
@Service
public class BusinessRelationServiceImpl extends ServiceImpl<EntRelationMapper, EntRelation> implements BusinessRelationService {

    @Resource
    private EntService entService;

    @Resource
    private EntRelationApiHandlerMapper entRelationApiHandlerMapper;

    @Resource
    private EntRelationExtMapper entRelationExtMapper;

    @Resource
    private UserService userService;

    @Override
    public void addCustomer(EntAddDto req) {
        add(req, BusinessRelationTypeEnum.CUSTOMER);
    }

    @Override
    public void addSupplier(EntAddDto req) {
        add(req, BusinessRelationTypeEnum.SUPPLIER);
    }

    @Transactional
    @Override
    public void add(EntAddDto req, BusinessRelationTypeEnum type) {
        String id = entService.add(req);
        EntRelation obj = baseMapper.queryEntRelationByEntId(id, type.getCode());
        if (obj == null) {
            obj = new EntRelation();
            obj.setEntId(id);
            obj.setCode(baseMapper.selectMax(type.getCode(),id));
            obj.setRelationType(type);
            obj.insert();
        }

        if(!obj.getTenantId().equals(SecurityUtils.getTenantId())){
            Integer code = obj.getCode();
            obj = new EntRelation();
            obj.setEntId(id);
            obj.setCode(code);
            obj.setRelationType(type);
            obj.insert();
        }
    }

    @Override
    public void add(String name, BusinessRelationTypeEnum type) {
        EntAddDto req = new EntAddDto();
        req.setName(name);
        req.setIndustryType(IndustryTypeEnum.Default);
        add(req, type);
    }

    @Transactional
    @Override
    public void update(EntRelationUpdateDto req) {
        EntRelation obj = baseMapper.selectById(req.getId());

        if (obj == null) {
            if (req.getRelationType() == null) {
                throw new BusinessException("往来单位类型不正确。");
            }
            obj = new EntRelation();
            obj.setCode(baseMapper.selectMax(req.getRelationType().getCode(),req.getEntId()));
            obj.setRelationType(req.getRelationType());
        }

        if (StringUtils.isNullOrEmpty(req.getEntId())) {
            EntAddDto addEnt = new EntAddDto();
            BeanUtils.copyProperties(req, addEnt);
            String entId = entService.add(addEnt);
            obj.setEntId(entId);
        } else {
            EntUpdateDto updateEnt = new EntUpdateDto();
            BeanUtils.copyProperties(req, updateEnt);
            updateEnt.setId(req.getEntId());
            obj.setEntId(req.getEntId());
            entService.update(updateEnt);
        }

        obj.insertOrUpdate();
    }

    @Transactional
    @Override
    public void delete(String id) {
        EntRelation obj = baseMapper.selectById(id);
        if (obj == null) {
            return;
        }

        LambdaQueryWrapper<EntRelation> lq = Wrappers.lambdaQuery();
        lq.eq(EntRelation::getEntId, obj.getEntId());
        lq.ne(EntRelation::getId, id);
        if (baseMapper.selectCount(lq) < 1) {
            entService.delete(obj.getEntId());
        }
        obj.deleteById();
    }

    @Override
    public void setOpenApiUser(String id, String userId) {
        EntRelation obj = baseMapper.selectById(id);
        if (obj == null) {
            return;
        }

        if (StringUtils.isNullOrEmpty(userId)) {
            obj.setOpenApiUserId(null);
            obj.updateById();
            return;
        }

        UserExt user = userService.getUserExt(userId);
        if (user == null) {
            throw new BusinessException("指定的用户没有找到。");
        }
        if (user.getType() != UserTypeEnum.API_REQUEST) {
            throw new BusinessException("指定的用户类型不正确。");
        }
        if (user.getIsDelete()) {
            throw new BusinessException("指定的用户已删除。");
        }
        if (user.getTenantIsDelete()) {
            throw new BusinessException("指定的用户所属的租户已失效。");
        }

        obj.setOpenApiUserId(userId);
        obj.updateById();
    }

    @Override
    public void setApiHandler(String entRelationId, String apiId, String handlerCode) {
        if (StringUtils.isNullOrEmpty(entRelationId)) {
            throw new BusinessException("未指定往来单位。");
        }
        if (StringUtils.isNullOrEmpty(apiId)) {
            throw new BusinessException("OpenApi 未指定。");
        }
        if (StringUtils.isNullOrEmpty(handlerCode)) {
            throw new BusinessException("OpenApi 处理器未指定。");
        }
        LambdaQueryWrapper<EntRelationApiHandler> lq = Wrappers.lambdaQuery();
        lq.eq(EntRelationApiHandler::getApiId, apiId);
        lq.eq(EntRelationApiHandler::getEntRelationId, entRelationId);
        lq.eq(EntRelationApiHandler::getHandlerCode, handlerCode);
        EntRelationApiHandler handler = entRelationApiHandlerMapper.selectOne(lq);
        if (handler == null) {
            handler = new EntRelationApiHandler();
        }
        handler.setApiId(apiId);
        handler.setEntRelationId(entRelationId);
        handler.setHandlerCode(handlerCode);
        handler.insertOrUpdate();
    }

    @Override
    public void deleteApiHandlerById(String id) {
        entRelationApiHandlerMapper.deleteById(id);
    }

    @Override
    public String queryEntRelation(String entId) {
        if (SecurityUtils.getUserContent().getType() != UserTypeEnum.API_REQUEST) {
            throw new BusinessException("当前请求 token 的 userType 不正确。");
        }
        int cnt = baseMapper.queryEntRelationCount(entId, SecurityUtils.getUserContent().getId());
        if (cnt > 1) {
            throw new BusinessException("当前的 token 被指向了多个往来单位。");
        } else if (cnt < 1) {
            throw new BusinessException("当前往来单位未配置 token 。");
        }
        EntRelation obj = baseMapper.queryEntRelationId(entId, SecurityUtils.getUserContent().getId());
        if (obj == null) {
            throw new BusinessException("往来单位信息没有找到。");
        }
        if (!obj.getEntId().equals(entId)) {
            throw new BusinessException("往来单位与当前Token所属的单位不一致。");
        }
        return obj.getId();
    }

    @Override
    public List<EntRelationApiHandlerDto> queryApiHandler(String entRelationId) {
        //LambdaQueryWrapper<EntRelationApiHandler> lq = Wrappers.lambdaQuery();
        //lq.eq(EntRelationApiHandler::getEntRelationId, entRelationId);
        //return entRelationApiHandlerMapper.selectList(lq).stream().map(s -> {
//        return entRelationApiHandlerMapper.selectByEntRelationId(entRelationId).stream().map(s -> {
//            EntRelationApiHandlerDto obj = new EntRelationApiHandlerDto();
//            obj.setId(s.getId());
//            obj.setApiId(s.getApiId());
//            obj.setEntName(baseMapper.queryEntNameByEntRelationId(s.getEntRelationId()));
//            obj.setApiId(s.getApiId());
//
//            OpenApiConfig config = openApiConfigService.queryById(s.getApiId());
//            if (config == null) {
//                throw new BusinessException("无效的OpenApi配置");
//            }
//            obj.setApiCode(config.getCode());
//            obj.setApiDesc(config.getDesc());
//            obj.setHandlerCode(s.getHandlerCode());
//            //obj.setHandlerDesc(s.gethand);
//            return obj;
//        }).collect(Collectors.toList());
        return null;
    }

    @Override
    public EntRelationApiHandlerDto queryApiHandlerById(String id) {
//        EntRelationApiHandler s = entRelationApiHandlerMapper.selectById(id);
//        EntRelationApiHandlerDto obj = new EntRelationApiHandlerDto();
//        obj.setId(s.getId());
//        obj.setApiId(s.getApiId());
//        obj.setEntRelationId(s.getEntRelationId());
//        obj.setEntName(baseMapper.queryEntNameByEntRelationId(s.getEntRelationId()));
//        obj.setApiId(s.getApiId());
//        OpenApiConfig config = openApiConfigService.queryById(s.getApiId());
//        if (config == null) {
//            throw new BusinessException("无效的OpenApi配置");
//        }
//        obj.setApiCode(config.getCode());
//        obj.setApiDesc(config.getDesc());
//        obj.setHandlerCode(s.getHandlerCode());
//        //obj.setHandlerDesc(s.gethand);
//        return obj;
        return null;
    }

    @Override
    public EntRelationApiHandlerDto queryApiHandler(String apiId, String entId, BusinessRelationTypeEnum businessRelationTypeEnum) {
        LambdaQueryWrapper<EntRelationExt> lq = Wrappers.lambdaQuery();
        lq.eq(EntRelationExt::getEntId, entId);
        lq.eq(EntRelationExt::getRelationType, businessRelationTypeEnum);
        lq.eq(EntRelationExt::getIsDelete, false);
        List<EntRelationExt> list = entRelationExtMapper.selectList(lq);
        if (list.size() > 1) {
            throw new BusinessException("指定的往来单位存在重复的数据。");
        }

        if (list.stream().findFirst().isPresent()) {
            Optional<EntRelationExt> obj = list.stream().findFirst();
            EntRelationApiHandlerDto ret = new EntRelationApiHandlerDto();
            ret.setEntId(obj.get().getEntId());
            ret.setId(obj.get().getId());

            // TODO: 2021/3/9

            return ret;
        } else {
            return null;
        }
    }

    @Override
    public void setTempContractSend(String id) {
        EntRelation obj = baseMapper.selectById(id);
        if (obj == null) {
            LambdaQueryWrapper<EntRelation> lq = Wrappers.lambdaQuery();
            lq.eq(EntRelation::getEntId, id);
            obj = baseMapper.selectOne(lq);
            if (obj == null) {
                return;
            }
        }

        obj.setIsTempContractSend(!obj.getIsTempContractSend());
        obj.updateById();
    }

    @Override
    public List<EntRelation> queryTempContractSend() {
        LambdaQueryWrapper<EntRelation> lq = Wrappers.lambdaQuery();
        lq.eq(EntRelation::getIsTempContractSend, true);
        return baseMapper.selectList(lq);
    }

    @Override
    public IPage<EntRelationDto> query(String searchText, BusinessRelationTypeEnum type, int pageSize, int pageIndex) {
        IPage<EntRelationExt> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<EntRelationExt> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(EntRelationExt::getName, searchText);
        }
        if (type != null) {
            lq.eq(EntRelationExt::getRelationType, type);
        }
        lq.orderByDesc(EntRelationExt::getCode);
        IPage<EntRelationExt> sourceList = entRelationExtMapper.selectPage(page, lq);
        IPage<EntRelationDto> retList = new Page<>();
        retList.setCurrent(sourceList.getCurrent());
        retList.setPages(sourceList.getPages());
        retList.setSize(sourceList.getSize());
        retList.setTotal(sourceList.getTotal());
        retList.setRecords(sourceList.getRecords().stream().map(s -> {
            EntRelationDto obj = new EntRelationDto();
            BeanUtils.copyProperties(s, obj);
            //obj.setBalanceMoney(businessRechargeService.queryBalance(s.getId()));
            return obj;
        }).collect(Collectors.toList()));
        return retList;
    }

    @Override
    public List<BusinessSupplyEntDto> querySupplyBySku(String skuId) {
        return null;

    }

    @Override
    public EntRelationExt queryCustomerById(String entId) {
        LambdaQueryWrapper<EntRelationExt> lq = Wrappers.lambdaQuery();
        lq.eq(EntRelationExt::getEntId, entId);
        lq.eq(EntRelationExt::getRelationType, BusinessRelationTypeEnum.CUSTOMER);
        lq.eq(EntRelationExt::getIsDelete, false);
        Optional<EntRelationExt> ret = entRelationExtMapper.selectList(lq).stream().findFirst();
        if (ret.isPresent()) {
            return ret.get();
        } else {
            return null;
        }
    }

    @Override
    public EntRelationExt querySupplierById(String entId) {
        LambdaQueryWrapper<EntRelationExt> lq = Wrappers.lambdaQuery();
        lq.eq(EntRelationExt::getEntId, entId);
        lq.eq(EntRelationExt::getRelationType, BusinessRelationTypeEnum.SUPPLIER);
        lq.eq(EntRelationExt::getIsDelete, false);
        Optional<EntRelationExt> ret = entRelationExtMapper.selectList(lq).stream().findFirst();
        if (ret.isPresent()) {
            return ret.get();
        } else {
            return null;
        }
    }

    @Override
    public EntRelationExt queryByEnt(String entId) {
        LambdaQueryWrapper<EntRelationExt> lq = Wrappers.lambdaQuery();
        lq.eq(EntRelationExt::getEntId, entId);
        lq.eq(EntRelationExt::getIsDelete, false);
        List<EntRelationExt> list = entRelationExtMapper.selectList(lq);
        if (list.size() <= 0) {
            throw new BusinessException(String.format("指定的单位不是【%s】的往来单位。", SecurityUtils.getUserContent().getEntName()));
        }
        return list.stream().findFirst().get();
    }

    @Override
    public EntRelationExt queryById(String id) {
        return entRelationExtMapper.selectById(id);
    }
}
